home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / text / print / post_src_186enh.lha / postband.c < prev    next >
C/C++ Source or Header  |  1993-01-27  |  21KB  |  817 lines

  1. /* Band rendering print driver for Post.  File "postband.c"
  2.  * (C) Adrian Aylward 1989, 1991
  3.  *
  4.  * You may freely copy, use, and modify this file.
  5.  *
  6.  * This file is a PostScript program driver that splits a PostScript file
  7.  * that conforms to the structuring conventions and calls Post to print
  8.  * it in a series of bands, even if there is not enough memory for a full
  9.  * page buffer.  It is totally Amiga specific.
  10.  *
  11.  * The program was tested using Lattice C V5.05.  It has various Lattice
  12.  * dependencies.
  13.  *
  14.  * V1.6 first full source release
  15.  */
  16.  
  17. # include <dos.h>
  18. # include <devices/printer.h>
  19. # include <devices/prtbase.h>
  20. # include <exec/exec.h>
  21. # include <exec/execbase.h>
  22. # include <exec/tasks.h>
  23. # include <graphics/gfx.h>
  24. # include <graphics/rastport.h>
  25. # include <proto/dos.h>
  26. # include <proto/exec.h>
  27. # include <stdio.h>
  28. # include <string.h>
  29.  
  30. # include "postlib.h"
  31.  
  32. # undef  POSTVERNO
  33. # define POSTVERNO 15  /* We need post.library version 1.5+ */
  34.  
  35. /* Assembler routines */
  36.  
  37. extern void insertbreak(void);
  38. extern void deletebreak(void);
  39. extern void insertftrap(void);
  40. extern void deleteftrap(void);
  41.  
  42. /* Routines defined and referenced only within this module */
  43.  
  44. extern void prints(BPTR fh, char *string);
  45. extern void errmsg(char *string);
  46. extern void setprinter(void);
  47. extern void setprintden(void);
  48. extern int  strtoint(char **sp, int *ip);
  49. extern void __saveds __asm copypage(register __d0 int num);
  50. extern void printpage(void);
  51. extern void splitpage(void);
  52.  
  53. /* External data (initialised to zero) */
  54.  
  55. int retcode, errcode, ioerror;
  56.  
  57. int arec;
  58.  
  59. BPTR errfh;
  60.  
  61. int ybase;
  62. int prologue, trailer;
  63. FILE *printfile;
  64.  
  65. struct library *PSbase;
  66. struct PSparm parm;
  67.  
  68. struct BitMap bitmap;
  69. struct ColorMap colormap;
  70.  
  71. int propen, prden;
  72. struct IODRPReq prreq;
  73. struct PrinterData *prdata;
  74. struct PrinterExtendedData *prextdata;
  75. struct Preferences *prprefs;
  76. struct RastPort prrast;
  77. struct MsgPort *prport;
  78. ULONG prsig;
  79. UBYTE prstatus[2];
  80.  
  81. int breakset, ftrapset;
  82.  
  83. /* Colour tables.  The default color map type is a vector or UWORD RGB
  84.  * values.  The colours are inverted as we set a bit in the bitmap whenever
  85.  * we want to place a drop of (black or cyan/magenta/yellow) ink */
  86.  
  87. static UWORD bcolors[2] =  /* Black and white */
  88. {   0xfff, 0x000                /* White   black */
  89. };
  90.  
  91. static UWORD ccolors[16] = /* Colour (RGB or CMYK) */
  92. {   0xfff, 0x0ff, 0xf0f, 0x00f, /* White   cyan    magenta blue */
  93.     0xff0, 0x0f0, 0xf00, 0x000, /* Yellow  green   red     black */
  94.     0x000, 0x000, 0x000, 0x000, /* Black */
  95.     0x000, 0x000, 0x000, 0x000  /* Black */
  96. };
  97.  
  98. /* Arguments */
  99.  
  100. int argfilec, argsizec, argmemc;
  101. char *argprint;
  102. char *argfilev[5], *argsizev[5], *argmemv[5];
  103. char *argkey[] =
  104. {   "PRINT", "SIZE", "MEM", NULL };
  105.  
  106. /* Startup code */
  107.  
  108. extern void main(int argc, char **argv);
  109.  
  110. void _main(char *line)
  111. {   char *argv[32];
  112.     int argc;
  113.  
  114.     /* Parse the arguments to break words and strip quotes.  N.B. the
  115.      * main program can determine that the arument was quoted by inspecting
  116.      * the preceeding character */
  117.  
  118.     argc = 0;
  119.     if (line == NULL) goto endline;
  120.     for (;;)
  121.     {   while (*line == ' ' || *line == '\t' || *line == '\n') line++;
  122.         if (*line == 0) break;
  123.         if (argc == 32)
  124.         {   argc = 0;
  125.             goto endline;
  126.         }
  127.         if (*line == '"')
  128.         {   argv[argc] = ++line;
  129.             while (*line != '"')
  130.             {   if (*line == 0)
  131.                 {   argc = 0;
  132.                     goto endline;
  133.                 }
  134.                 line++;
  135.             }
  136.         }
  137.         else
  138.         {   argv[argc] = line;
  139.             while (*line != ' ' && *line != '\t' && *line != '\n')
  140.             {   if (*line == 0)
  141.                 {   argc++;
  142.                     goto endline;
  143.                 }
  144.                 line++;
  145.             }
  146.         }
  147.         *line++ = 0;
  148.         argc++;
  149.     }
  150. endline:
  151.  
  152.     /* Set up the standard input/output files */
  153.  
  154.     errfh = Open("*", MODE_OLDFILE);
  155.     if (errfh == NULL)
  156.     {   retcode = 20;
  157.         goto tidyexit;
  158.     }
  159.  
  160.     /* Call the main program  */
  161.  
  162.     main(argc, argv);
  163.  
  164.     /* Tidy up and exit */
  165.  
  166. tidyexit:
  167.     if (errfh) Close(errfh);
  168.  
  169.     XCEXIT(retcode);
  170. }
  171.  
  172. /* Main program */
  173.  
  174. void main(int argc, char **argv)
  175. {   char *s;
  176.     int *ip, i, ch;
  177.     int xsize, ysize, ssize, xoff, yoff, xden, yden, pden;
  178.  
  179.     /* Open the libraries */
  180.  
  181.     PSbase = OpenLibrary("post.library", POSTVERNO);
  182.     if (PSbase == NULL)
  183.     {   errmsg("can't open post.library");
  184.         goto errorexit;
  185.     }
  186.  
  187.     /* Parse the arguments and keywords.  See the usage string below */
  188.  
  189.     argc--;
  190.     argv++;
  191.     if (argc == 0 || (argc == 1 && strcmp(*argv, "?") == 0)) goto usage;
  192.  
  193.     while (argc--)
  194.     {   s = *argv++;
  195.         i = -1;
  196.         if (s[-1] != '"')
  197.             for (;;)
  198.             {   i++;
  199.                 if (argkey[i] == NULL)
  200.                 {   i = -1;
  201.                     break;
  202.                 }
  203.                 if (stricmp(s, argkey[i]) == 0) break;
  204.             }
  205.         switch (i)
  206.         {   case  0:    /* PRINT */
  207.                 if (argc == 0) goto badargs;
  208.                 argc--;
  209.                 argprint = *argv++;
  210.                 break;
  211.  
  212.             case  1:    /* SIZE */
  213.                 if (argc == 0) goto badargs;
  214.                 argc--;
  215.                 if (argsizec == 5) goto badargs;
  216.                 argsizev[argsizec++] = *argv++;
  217.                 break;
  218.  
  219.             case  2:    /* MEM */
  220.                 if (argc == 0) goto badargs;
  221.                 argc--;
  222.                 if (argmemc == 5) goto badargs;
  223.                 argmemv[argmemc++] = *argv++;
  224.                 break;
  225.  
  226.             default:
  227.                 if (argfilec == 5) goto badargs;
  228.                 argfilev[argfilec++] = s;
  229.         }
  230.     }
  231.     if (argprint == NULL) goto badargs;
  232.  
  233.     /* Get up the default page size from the printer preferences */
  234.  
  235.     bitmap.BytesPerRow = 1;
  236.     bitmap.Rows = 1;
  237.     bitmap.Flags = 0;
  238.     bitmap.Depth = parm.page.depth = 3;
  239.     setprinter();
  240.     parm.page.xoff = 0;
  241.     parm.page.yoff = 0;
  242.     if (prport == NULL)
  243.     {   errmsg("can't open printer device");
  244.         goto errorexit;
  245.     }
  246.     parm.page.ydir = -1;
  247.  
  248.     /* Parse the "SIZE xyod..s..p.bc." options */
  249.  
  250.     xsize = ysize = ssize = xden = yden = pden = 0;
  251.     for (i = 0; i < argsizec; i++)
  252.     {   s = argsizev[i];
  253.         for (;;)
  254.         {   ch = *s++;
  255.             if (ch == 0) break;
  256.             ch = tolower(ch);
  257.             switch (ch)
  258.             {   case 'x':
  259.                     if      (tolower(*s) == 'o')
  260.                     {   s++;
  261.                         if (!strtoint(&s, &xoff)) goto badvalue;
  262.                         parm.page.xoff = xoff;
  263.                         continue;
  264.                     }
  265.                     else if (tolower(*s) == 'd')
  266.                     {   s++;
  267.                         ip = &xden;
  268.                     }
  269.                     else
  270.                         ip = &xsize;
  271.                     break;
  272.  
  273.                 case 'y':
  274.                     if      (tolower(*s) == 'o')
  275.                     {   s++;
  276.                         if (!strtoint(&s, &yoff)) goto badvalue;
  277.                         parm.page.yoff = yoff;
  278.                         continue;
  279.                     }
  280.                     else if (tolower(*s) == 'd')
  281.                     {   s++;
  282.                         ip = &yden;
  283.                     }
  284.                     else
  285.                         ip = &ysize;
  286.                     break;
  287.  
  288.                 case 's':
  289.                     ip = &ssize;
  290.                     break;
  291.  
  292.                 case 'p':
  293.                     ip = &pden;
  294.                     break;
  295.  
  296.                 case 'd':
  297.                 {   if (!strtoint(&s, &xden)) goto badvalue;
  298.                     yden = xden;
  299.                     continue;
  300.                 }
  301.  
  302.                 case 'b':
  303.                     parm.page.depth = 1;
  304.                     continue;
  305.  
  306.                 case 'c':
  307.                     ch = *s;
  308.                     if      (ch == '3')
  309.                     {   s++;
  310.                         parm.page.depth = 3;
  311.                     }
  312.                     else if (ch == '4')
  313.                     {   s++;
  314.                         parm.page.depth  = 4;
  315.                     }
  316.                     else
  317.                         parm.page.depth = 3;
  318.                     continue;
  319.  
  320.                 default:
  321.                     goto badvalue;
  322.             }
  323.             if (!strtoint(&s, ip)) goto badvalue;
  324.         }
  325.     }
  326.     if (xden != 0) parm.page.xden = xden;
  327.     if (yden != 0) parm.page.yden = yden;
  328.     if (xsize != 0) parm.page.xsize = xsize;
  329.     if (ysize != 0) parm.page.ysize = ysize;
  330.     if (pden != 0)
  331.     {   prden = pden;
  332.         setprintden();
  333.     }
  334.  
  335.     /* Parse the "MEM fhlv.." options */
  336.  
  337.     for (i = 0; i < argmemc; i++)
  338.     {   s = argmemv[i];
  339.         for (;;)
  340.         {   ch = *s++;
  341.             if (ch == 0) break;
  342.             ch = tolower(ch);
  343.             switch (ch)
  344.             {   case 'f':
  345.                     ip = &parm.memflen;
  346.                     break;
  347.  
  348.                 case 'h':
  349.                     ip = &parm.memhlen;
  350.                     break;
  351.  
  352.                 case 'l':
  353.                     ip = &parm.memllen;
  354.                     break;
  355.  
  356.                 case 'v':
  357.                     ip = &parm.memvlen;
  358.                     break;
  359.  
  360.                 default:
  361.                     goto badvalue;
  362.             }
  363.             if (!strtoint(&s, ip)) goto badvalue;
  364.         }
  365.     }
  366.  
  367.     /* Set up the color map according to the number of bitplanes */
  368.  
  369.     colormap.Count = 1 << parm.page.depth;
  370.     if (parm.page.depth == 1)
  371.         colormap.ColorTable = (APTR) bcolors;
  372.     else
  373.         colormap.ColorTable = (APTR) ccolors;
  374.  
  375.     parm.page.ybase = 0;
  376.     parm.page.yheight = parm.page.ysize;
  377.     if (ssize != 0 && ssize < parm.page.ysize) parm.page.ysize = ssize;
  378.     if (parm.page.xsize == 0 || parm.page.ysize == 0)
  379.     {   errmsg("page size not set in preferences");
  380.         goto errorexit;
  381.     }
  382.     parm.page.xbytes = (parm.page.xsize + 15) >> 3 & 0xfffffffe;
  383.     parm.page.len = parm.page.xbytes * parm.page.ysize;
  384.  
  385.     /* Allocate the page buffer */
  386.  
  387.     for (i = 0; i < parm.page.depth; i++)
  388.     {   if ((parm.page.buf[i] =
  389.                 AllocMem(parm.page.len, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
  390.         {   errmsg("can't get page buffer");
  391.             goto errorexit;
  392.         }
  393.     }
  394.  
  395.     /* Initialise the bitmap */
  396.  
  397.     bitmap.BytesPerRow = parm.page.xbytes;
  398.     bitmap.Rows = parm.page.ysize;
  399.     bitmap.Flags = 0;
  400.     bitmap.Depth = parm.page.depth;
  401.     memcpy((char *) bitmap.Planes, (char *) parm.page.buf,
  402.            sizeof bitmap.Planes);
  403.  
  404.     /* Open the print file and check the header */
  405.  
  406.     printfile = fopen(argprint, "r");
  407.     if (printfile == NULL)
  408.     {   errmsg("can't open print file\n");
  409.         goto errorexit;
  410.     }
  411.     s = "%!PS-Adobe-";
  412.     while (*s)
  413.     {   ch = fgetc(printfile);
  414.         if (ch != *s++) goto pferror;
  415.     }
  416.     for (;;)
  417.     {   ch = fgetc(printfile);
  418.         if (ch == '\n') break;
  419.         if (ch == EOF) goto pferror;
  420.     }
  421.     prologue = 1;
  422.     trailer = 0;
  423.  
  424.     /* Initialise for interpretation */
  425.  
  426.     insertbreak();
  427.     SetExcept(~0, SIGBREAKF_CTRL_C);
  428.     breakset = 1;
  429.     insertftrap();
  430.     ftrapset = 1;
  431.  
  432.     parm.copyfunc = (APTR) copypage;
  433.  
  434.     parm.infh = Input();
  435.     parm.outfh = Output();
  436.     parm.errfh = errfh;
  437.  
  438.     arec = PScreateact(&parm);
  439.     if (arec == 0)
  440.     {   errmsg("can't get memory");
  441.         goto errorexit;
  442.     }
  443.     if ((unsigned) arec <= errmax)
  444.     {   arec = 0;
  445.         retcode = 10;
  446.         goto tidyexit;
  447.     }
  448.  
  449.     /* Interpret the argument files */
  450.  
  451.     for (i = 0; i < argfilec; i++)
  452.         if (PSintstring(arec, argfilev[i],
  453.                         -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE) != 0)
  454.         {   retcode = 10;
  455.             goto tidyexit;
  456.         }
  457.  
  458.     /* Interpret the prologue and each page */
  459.  
  460.     for (;;)
  461.     {   if (trailer) break;
  462.         splitpage();
  463.         if (retcode != 0) break;
  464.         ybase = 0;
  465.         if (PSintstring(arec,
  466.                         prologue ?
  467.             "(t:postband.ps) run" :
  468.             "currentband 1 sub{setband (t:postband.ps) run} for 0 setband",
  469.                         -1, PSFLAGSTRING) != 0)
  470.         {   retcode = 10;
  471.             break;
  472.         }
  473.         prologue = 0;
  474.     }
  475.  
  476.     goto tidyexit;
  477.  
  478.     /* File format error */
  479.  
  480. pferror:
  481.     errmsg("print file not PostScript conforming");
  482.     goto errorexit;
  483.  
  484.     /* Argument errors and usage query */
  485.  
  486. badargs:
  487.     errmsg("arguments bad, or value missing");
  488.     goto badusage;
  489.  
  490. badvalue:
  491.     errmsg("argument bad value");
  492.  
  493. badusage:
  494.     retcode = 20;
  495.  
  496. usage:
  497.     errmsg("usage:\n"
  498.     "    postband [files...] PRINT file [SIZE xyod..s..p.bc.] [MEM fhlv..]");
  499.     goto tidyexit;
  500.  
  501.     /* Tidy up and exit */
  502.  
  503. errorexit:
  504.     retcode = 20;
  505.  
  506. tidyexit:
  507.     DeleteFile("t:postband.ps");
  508.     if (printfile) fclose(printfile);
  509.  
  510.     if (breakset)
  511.     {   SetExcept(0, SIGBREAKF_CTRL_C);
  512.         deletebreak();
  513.         breakset = 0;
  514.     }
  515.     if (ftrapset)
  516.     {   deleteftrap();
  517.         ftrapset = 0;
  518.     }
  519.  
  520.     if (arec) PSdeleteact(arec);
  521.  
  522.     for (i = 0; i < parm.page.depth; i++)
  523.         if (parm.page.buf[i])
  524.         {   FreeMem(parm.page.buf[i], parm.page.len);
  525.             parm.page.buf[i] = NULL;
  526.         }
  527.  
  528.     if (propen) CloseDevice((struct IORequest *) &prreq);
  529.     if (prport) DeletePort(prport);
  530.  
  531.     if (PSbase)  CloseLibrary(PSbase);
  532. }
  533.  
  534. /* Print a string to a DOS file handle */
  535.  
  536. void prints(BPTR fh, char *string)
  537. {   Write(fh, string, strlen(string));
  538. }
  539.  
  540. /* Display an error message */
  541.  
  542. void errmsg(char *string)
  543. {   prints(errfh, "postband: ");
  544.     prints(errfh, string);
  545.     prints(errfh, "\n");
  546. }
  547.  
  548. /* Open the printer device and set up the page size */
  549.  
  550. void setprinter(void)
  551. {   if (propen == 0)
  552.     {   if (OpenDevice("printer.device", 0,
  553.                        (struct IOReqest *) &prreq, 0) != 0)
  554.             return;
  555.         propen = 1;
  556.     }
  557.     if (prport == NULL)
  558.     {   prport = CreatePort(NULL, 0);
  559.         if (prport == NULL) return;
  560.         prreq.io_Message.mn_ReplyPort = prport;
  561.         prsig = 1 << prport->mp_SigBit;
  562.         prdata = (struct PrinterData *) prreq.io_Device;
  563.         prextdata = &prdata->pd_SegmentData->ps_PED;
  564.         prprefs = &prdata->pd_Preferences;
  565.         prden = prprefs->PrintDensity;
  566.     }
  567.     if ((prprefs->PrintShade & SHADE_COLOR) == 0) parm.page.depth = 1;
  568.     setprintden();
  569. }
  570.  
  571. /* Set the printer density */
  572.  
  573. void setprintden(void)
  574. {   int pxsize, pysize;
  575.  
  576.     /* New density, call the device driver to change its extended data.  No
  577.      * error check */
  578.  
  579.     if (prden > 7) prden = 7;
  580.     if (prden != prprefs->PrintDensity)
  581.     {   prreq.io_Command = PRD_DUMPRPORT;
  582.         prrast.BitMap = &bitmap;
  583.         prreq.io_RastPort = &prrast;
  584.         prreq.io_ColorMap = (struct ColorMap *) &colormap;
  585.         prreq.io_Modes = 0;
  586.         prreq.io_SrcX = 0;
  587.         prreq.io_SrcY = 0;
  588.         prreq.io_SrcWidth = 1;
  589.         prreq.io_SrcHeight = 1;
  590.         prreq.io_DestCols = 1;
  591.         prreq.io_DestRows = 1;
  592.         prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_NOPRINT;
  593.         prprefs->PrintDensity = prden;
  594.         DoIO((struct IORequest *) &prreq);
  595.     }
  596.  
  597.     /* Extract the page size and density from the printer device preferences
  598.      * and extended data */
  599.  
  600.     parm.page.xden = prextdata->ped_XDotsInch;
  601.     parm.page.yden = prextdata->ped_YDotsInch;
  602.     if      (prprefs->PrintFlags & PIXEL_DIMENSIONS)
  603.     {   pxsize = prprefs->PrintMaxWidth;
  604.         pysize = prprefs->PrintMaxHeight;
  605.     }
  606.     else if (prprefs->PrintFlags &
  607.                 (BOUNDED_DIMENSIONS|ABSOLUTE_DIMENSIONS))
  608.     {   pxsize = prprefs->PrintMaxWidth * parm.page.xden / 10;
  609.         pysize = prprefs->PrintMaxHeight * parm.page.yden / 10;
  610.     }
  611.     if (pxsize != 0) parm.page.xsize = pxsize;
  612.     if (pysize != 0) parm.page.ysize = pysize;
  613. }
  614.  
  615. /* String to integer conversion; digits only, with error check */
  616.  
  617. int strtoint(char **sp, int *ip)
  618. {   char *s = *sp;
  619.     int i = 0;
  620.     int ch;
  621.     for (;;)
  622.     {   ch = *s;
  623.         if (ch < '0' || ch > '9') break;
  624.         i = i * 10 + (ch - '0');
  625.         s++;
  626.     }
  627.     if (s == *sp)
  628.         return 0;
  629.     else
  630.     {   *sp = s;
  631.         *ip = i;
  632.         return 1;
  633.     }
  634. }
  635.  
  636. /* Signal an interrupt */
  637.  
  638. void __saveds sigint()
  639. {   PSsignalint(arec, 1);
  640. }
  641.  
  642. /* Signal a floating point error */
  643.  
  644. void __saveds sigfpe()
  645. {   PSsignalfpe(arec);
  646. }
  647.  
  648. /* Copy the page to the output */
  649.  
  650. void __saveds __asm copypage(register __d0 int num)
  651. {   ioerror = 0;
  652.     printpage();
  653.     if (ioerror) PSerror(arec, ioerror);
  654. }
  655.  
  656. /* Print the page */
  657.  
  658. void printpage()
  659. {   ULONG sig;
  660.     UWORD prflags;
  661.  
  662.     /* Disable break exceptions so we can wait on the signal instead */
  663.  
  664.     SetExcept(0, SIGBREAKF_CTRL_C);
  665.     breakset = 0;
  666.  
  667.     /* First check the printer is ready */
  668.  
  669.     prreq.io_Command = PRD_QUERY;
  670.     ((struct IOStdReq *) &prreq)->io_Data = (APTR) prstatus;
  671.     if (DoIO((struct IORequest *) &prreq))
  672.     {   ioerror = errioerror;
  673.         return;
  674.     }
  675.     if (((struct IOStdReq *) &prreq)->io_Actual == 1 && prstatus[0] & 3 != 0)
  676.         errmsg("printer not ready (CTRL/C to abort)");
  677.  
  678.     /* Now dump the page */
  679.  
  680.     prrast.BitMap = &bitmap;
  681.     prreq.io_Command = PRD_DUMPRPORT;
  682.     prreq.io_RastPort = &prrast;
  683.     prreq.io_ColorMap = (struct ColorMap *) &colormap;
  684.     prreq.io_Modes = 0;
  685.     prreq.io_SrcX = 0;
  686.     prreq.io_SrcY = 0;
  687.     prreq.io_SrcWidth = parm.page.xsize;
  688.     prreq.io_SrcHeight = parm.page.ysize;
  689.     prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_TRUSTME;
  690.     if (ybase + parm.page.ysize >= parm.page.yheight)
  691.         prreq.io_SrcHeight = parm.page.yheight - ybase;
  692.     else
  693.         prreq.io_Special |= SPECIAL_NOFORMFEED;
  694.     if (prextdata->ped_MaxXDots != 0)
  695.         if (prreq.io_SrcWidth > prextdata->ped_MaxXDots)
  696.             prreq.io_SrcWidth = prextdata->ped_MaxXDots;
  697.     if (prextdata->ped_MaxYDots != 0)
  698.         if (prreq.io_SrcHeight > prextdata->ped_MaxYDots)
  699.             prreq.io_SrcHeight = prextdata->ped_MaxYDots;
  700.     prreq.io_DestCols = prreq.io_SrcWidth;
  701.     prreq.io_DestRows = prreq.io_SrcHeight;
  702.     ybase += prreq.io_SrcHeight;
  703.     prflags = prprefs->PrintFlags;
  704.     prprefs->PrintFlags = prflags & ~DIMENSIONS_MASK | IGNORE_DIMENSIONS;
  705.     prprefs->PrintAspect = ASPECT_HORIZ;
  706.  
  707.     /* We use asynchronous IO so we can abort it with a CTRL/C */
  708.  
  709.     SendIO((struct IORequest *) &prreq);
  710.  
  711.     for (;;)
  712.     {   sig = Wait(prsig | SIGBREAKF_CTRL_C);
  713.         if (sig & SIGBREAKF_CTRL_C)
  714.         {   AbortIO((struct IORequest *) &prreq);
  715.             WaitIO((struct IORequest *) &prreq);
  716.             ioerror = errioerror;
  717.             break;
  718.         }
  719.         if (GetMsg(prport))
  720.             break;
  721.     }
  722.     if (prreq.io_Error != 0) ioerror = errioerror;
  723.  
  724.     /* Restore break exceptions */
  725.  
  726.     SetExcept(~0, SIGBREAKF_CTRL_C);
  727.     breakset = 1;
  728.  
  729.     prprefs->PrintFlags = prflags;
  730. }
  731.  
  732. /* Split the prologue or next page of the print file into the temp file */
  733.  
  734. void splitpage(void)
  735. {   FILE *tempfile;
  736.     char *s;
  737.     int matched, ch;
  738.  
  739.     tempfile = fopen("t:postband.ps", "w");
  740.     if (tempfile == NULL)
  741.     {   errmsg("can't open temporary file");
  742.         retcode = 20;
  743.         return;
  744.     }
  745.  
  746.     matched = 0;
  747.     for (;;)
  748.     {   ch = fgetc(printfile);
  749.  
  750.         /* Comment lines are not copied */
  751.  
  752.         if (ch == '%')
  753.         {   ch = fgetc(printfile);
  754.  
  755.             /* %% Comments may be a trailer */
  756.  
  757.             if (ch == '%')
  758.             {   ch = fgetc(printfile);
  759.                 if      (ch == 'P')
  760.                 {   s = "age:";
  761.                     while (*s)
  762.                     {   ch = fgetc(printfile);
  763.                         if (ch != *s++) goto nomatch;
  764.                     }
  765.                     matched = 1;
  766.                 }
  767.                 else if (ch == 'T')
  768.                 {   s = "railer";
  769.                     while (*s)
  770.                     {   ch = fgetc(printfile);
  771.                         if (ch != *s++) goto nomatch;
  772.                     }
  773.                     if (prologue) goto pferror;
  774.                     matched = 1;
  775.                     trailer = 1;
  776.                 }
  777.             }
  778.  
  779.             /* Skip the rest of the comment */
  780.  
  781. nomatch:    if (ch == EOF) goto pferror;
  782.             for (;;)
  783.             {   ch = fgetc(printfile);
  784.                 if (ch == '\n') break;
  785.                 if (ch == EOF) goto pferror;
  786.             }
  787.         }
  788.  
  789.         /* All other lines are copied to the temp file */
  790.  
  791.         else
  792.         {   for (;;)
  793.             {   if (ch == EOF) goto pferror;
  794.                 if (fputc(ch, tempfile) == EOF) goto tferror;
  795.                 if (ch == '\n') break;
  796.                 ch = fgetc(printfile);
  797.             }
  798.         }
  799.         if (matched) break;
  800.     }
  801.     if (fclose(tempfile) == EOF) goto tferror;
  802.     return;
  803.  
  804. pferror:
  805.     errmsg("print file not conforming or io error");
  806.     goto errorexit;
  807.  
  808. tferror:
  809.     errmsg("error with temporary file");
  810.  
  811. errorexit:
  812.     fclose(tempfile);
  813.     retcode = 20;
  814. }
  815.  
  816. /* End of file "postband.c" */
  817.